package io.renren.common.exception.global;

import io.renren.common.exception.MedicalException;
import io.renren.common.exception.ScriptCallException;
import io.renren.common.exception.ThreadPoolException;
import io.renren.common.result.R;
import io.renren.common.result.Result;
import io.renren.common.result.ResultCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.AuthorizationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.util.HashMap;
import java.util.Map;

/**
 * 统一的异常处理类，针对特殊异常
 */

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(NoHandlerFoundException.class)
    public R handlerNoFoundException(Exception e) {
        log.error(e.getMessage(), e);
        return R.error(404, "路径不存在，请检查路径是否正确");
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public R handleDuplicateKeyException(DuplicateKeyException e) {
        log.error(e.getMessage(), e);
        return R.error("数据库中已存在该记录");
    }

    @ExceptionHandler(AuthorizationException.class)
    public R handleAuthorizationException(AuthorizationException e) {
        log.error(e.getMessage(), e);
        return R.error("没有权限，请联系管理员授权");
    }

    @ExceptionHandler(Exception.class)
    public Result<Object> error(Exception e) {
        if (e instanceof ScriptCallException) {
            // 远程脚本调用错误 （远程调用模块异常）
            log.error(((ScriptCallException) e).getMsg());
            return Result.fail(null)
                    .message(((ScriptCallException) e).getMsg())
                    .code(((ScriptCallException) e).getCode());

        } else if (e instanceof ThreadPoolException) {
            // 线程池调用错误 （远程调用模块异常）
            log.error(e.getMessage());
            return Result
                    .fail(null).message(ResultCodeEnum.THREAD_POOL_ERROR.getMessage())
                    .code(ResultCodeEnum.THREAD_POOL_ERROR.getCode());

        } else if (e instanceof MedicalException) {
            // 医疗模块异常处理
            log.error(e.getMessage());
            return Result
                    .fail(null)
                    .message(((MedicalException) e).getMsg())
                    .code(((MedicalException) e).getCode());
        } else if (e instanceof MaxUploadSizeExceededException) {
            // 医疗模块异常处理
            log.error(e.getMessage());
            return Result
                    .fail(null)
                    .message(ResultCodeEnum.FILE_SIZE_ERROR.getMessage())
                    .code(ResultCodeEnum.FILE_SIZE_ERROR.getCode());

        } else if (e instanceof MethodArgumentNotValidException) {
            // 数据是否有效异常检验
            BindingResult bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
            // 将错误集合封装进入Map中
            Map<String, String> errorMap = new HashMap<>();
            bindingResult.getFieldErrors().forEach((item) -> errorMap.put(item.getField(), item.getDefaultMessage()));
            System.out.println(errorMap);
            return Result.fail(null).code(ResultCodeEnum.MODEL_INVALID_ERROR.getCode())
                    .message(ResultCodeEnum.MODEL_INVALID_ERROR.getMessage());
        } else {
            // 未知异常
            log.error("服务器出现未知异常：{}", e.getMessage());
            return Result.fail(null).code(ResultCodeEnum.SERVICE_UNKNOWN_ERROR.getCode()).message("服务端出现未知异常");
        }
    }

}
